<?php

namespace addons\wanlshop\library\WanlPay;

use app\admin\model\User;
use app\admin\model\wanlshop\Agent;
use app\admin\model\wanlshop\OfflineOrder;
use app\common\model\UserFinanceLog;
use app\admin\model\wanlshop\Address;
use app\admin\model\wanlshop\Share;
use app\api\model\wanlshop\ShopConfig;
use app\admin\model\wanlshop\OrderGoods;
use app\admin\model\wanlshop\Shop;
use app\api\controller\Thirdplatform;
use app\api\model\wanlshop\Order;
use app\api\model\wanlshop\PayOutTrade;
use App\Api\PrintService;
use app\common\library\Auth;
use app\admin\model\wanlshop\ShareOrder;
use app\admin\model\wanlshop\AgentOrder;
use addons\wanlshop\library\WanlChat\WanlChat;
use think\Db;
use think\Exception;
use fast\Http;
use WanlPay\Yansongda\Pay;
use WanlPay\Yansongda\Log;
use WanlPay\Supports\Str;

/**
 *
 * WanlPay 多终端支付
 * @author 深圳前海万联科技有限公司 <wanlshop@i36k.com>
 * @link http://www.wanlshop.com
 *
 * @careful 非FastAdmin购买授权，未经版权所有权人书面许可，不得自行复制到第三方系统使用、二次开发、分支、复制和商业使用！
 * @creationtime  2020年8月7日23:46:12
 * @lasttime 2021年9月27日00:48:32
 * @version V2.x https://pay.yansongda.cn/docs/v2/
 **/
class WanlPay
{
    private $type;
    private $method;
    private $code;

    public function __construct($type = '', $method = '', $code = '')
    {
        $auth = Auth::instance(); // 方式
        $this->wanlchat = new WanlChat();
        $this->type = $type;  // 类型
        $this->method = $method; // 方式
        $this->user_id = $auth->isLogin() ? $auth->id : 0; // 用户ID
        $this->request = \think\Request::instance();
        $this->code = $code; // 小程序code
    }

    /**
     * 支付
     */
    public function pay($order_id, $order_type)
    {
        \think\Log::error('wablpay.php pay');
        if ($this->user_id == 0) {
            return ['code' => 10001, 'msg' => '用户ID不存在'];
        }
        // 获取支付信息
        $pay = model('app\api\model\wanlshop\Pay')
            ->where('order_id', 'in', $order_id)
            ->where(['user_id' => $this->user_id, 'type' => $order_type == 'groups' ? 'groups' : 'goods'])
            ->select();
        // 1.0.8 升级
        $price = 0; // 付款金额
        $order_no = []; // 订单号
        $orderIds = []; // 订单id
        $pay_id = []; // 交易号
        foreach ($pay as $row) {
            $price = bcadd($price, $row['price'], 2); // 总价格
            $order_no[] = $row['order_no']; // 订单集
            $orderIds[] = $row['order_id']; // 订单id
            $pay_id[] = $row['id']; // 交易集
        }
        // 第三方支付订单 1.0.8
        $out_trade_no = date('YmdHis') . rand(10000000, 99999999) . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
        if ($this->type != 'balance') {
            $payOutTrade = model('app\api\model\wanlshop\PayOutTrade');
            $payOutTrade->out_trade_no = $out_trade_no;
            $payOutTrade->pay_id = $pay_id;
            $payOutTrade->order_id = $order_id;
            $payOutTrade->price = $price;
            $payOutTrade->save();
        }
        // 1.0.8升级 拼团订单
        if ($order_type == 'groups') {
            $title = '拼团订单-' . implode("_", $order_no);
            $model_order = model('app\api\model\wanlshop\groups\Order');
            $model_order_goods = model('app\api\model\wanlshop\groups\OrderGoods');
            $model_goods = model('app\api\model\wanlshop\groups\Goods');
        } else {
            $title = '商城订单-' . implode("_", $order_no);
            $model_order = model('app\api\model\wanlshop\Order');
            $model_order_goods = model('app\api\model\wanlshop\OrderGoods');
            $model_goods = model('app\api\model\wanlshop\Goods');
        }
        // 支付方式
        if ($this->type == 'balance') {
            // 支付列表
            $pay_list = [];
            // 订单列表
            $order_list = [];
            // 拼团列表
            $groups_list = [];
            // 拼团列表
            $groups_team_list = [];
            // 判断金额
            $user = model('app\common\model\User')->get($this->user_id);
            if (!$user || $user['money'] < $price) {
                return ['code' => 500, 'msg' => '余额不足本次支付'];
            }
            $result = false;
            $balance_no = date('YmdHis') . rand(10000000, 99999999);
            Db::startTrans();
            try {
                foreach ($pay as $row) {
                    $isAlone = false; // 拼团订单一般是单订单，暂可以这样操作
                    $groups_state = 'start'; // 拼团状态
                    foreach ($model_order_goods->where('order_id', $row['order_id'])->select() as $goods) {
                        if ($order_type == 'groups' && !empty($goods['group_type'])) {
                            if ($goods['group_type'] == 'alone') {
                                $isAlone = true;
                            } else {
                                // 查询团ID
                                $groups = model('app\api\model\wanlshop\groups\Groups')
                                    ->where(['group_no' => $goods['group_no']])
                                    ->find();
                                // 判断是否超团
                                $groups_team = model('app\api\model\wanlshop\groups\Team')
                                    ->where(['group_no' => $goods['group_no']])
                                    ->select();
                                // 已拼团总数量
                                $groups_team_count = count($groups_team);
                                if ($groups_team_count >= $groups['people_num'] || $groups['join_num'] >= $groups['people_num']) {
                                    $this->error(__('参与拼单失败，拼团已完成'));
                                }
                                // 判断是否具备成团条件
                                if (($groups['people_num'] - $groups_team_count) <= 1 || ($groups['people_num'] - $groups['join_num']) <= 1) {
                                    $groups_state = 'success';
                                    //调整其他拼团订单
                                    // 订单状态:1=待支付,2=待成团,3=待发货,4=待收货,5=待评论,6=已完成,7=已取消
                                    foreach ($groups_team as $team) {
                                        $order_list[] = ['id' => $team['order_id'], 'state' => 3, 'groupstime' => time()];
                                    }
                                }
                                // 拼团状态: ready=准备中,start=拼团中,success=已成团,fail=拼团失败,auto=自动成团
                                $groups_list[] = [
                                    'id' => $groups['id'],
                                    'join_num' => $groups['join_num'] + 1,
                                    'state' => $groups_state,
                                    'grouptime' => $groups_state === 'success' ? time() : NULL
                                ];
                                $groups_team_list[] = [
                                    'user_id' => $user['id'],
                                    'shop_id' => $goods['shop_id'],
                                    'group_no' => $goods['group_no'],
                                    'order_id' => $goods['order_id'],
                                    'order_goods_id' => $goods['id']
                                ];
                            }
                        }
                        // 新增付款人数、新增销量
                        $model_goods->where('id', $goods['goods_id'])->inc('payment')->inc('sales', $goods['number'])->update();
                    }
                    // 订单列表
                    if ($groups_state === 'success') {
                        $order_list[] = ['id' => $row['order_id'], 'state' => 3, 'paymenttime' => time(), 'groupstime' => time()];
                    } else {
                        $order_list[] = ['id' => $row['order_id'], 'state' => $isAlone ? 3 : 2, 'paymenttime' => time()];
                    }
                    // 支付列表
                    $pay_list[] = [
                        'id' => $row['id'],
                        'trade_no' => $balance_no, // 第三方交易号
                        'pay_type' => 0, // 支付类型:0=余额支付,1=微信支付,2=支付宝支付
                        'pay_state' => 1, // 支付状态 (支付回调):0=未支付,1=已支付,2=已退款
                        'total_amount' => $price, // 总金额
                        'actual_payment' => $row['price'], // 实际支付
                        'notice' => json_encode([
                            'type' => $this->type,
                            'user_id' => $user['id'],
                            'trade_no' => $balance_no,
                            'out_trade_no' => $row['pay_no'],
                            'amount' => $row['price'],
                            'total_amount' => $price,
                            'order_id' => $row['order_id'],
                            'trade_type' => 'BALANCE',
                            'version' => '1.0.0'
                        ])
                    ];

                    // 打印 同步订单 积分处理 返现给线下用户
                    \think\Log::error("extHandle {$row['order_id']} {$row['user_id']}");
                    $res = $this->extHandle($row['order_id'], $row['user_id']);
                    if ($res !== true) {
                        \think\Log::error("pay.extHandle_error:{$res}");
                        throw new Exception($res);
                    }
                }
                // 更新支付列表
                $result = model('app\api\model\wanlshop\Pay')->saveAll($pay_list);
                // 更新订单列表
                $result = $model_order->saveAll($order_list);

                // 修改用户金额
                if (count($order_no) == 1) {
                    $memo = $order_type == 'groups' ? '拼团' : '商品' . "订单余额支付:" . implode(',', $order_no);
                    $result = self::money(-$price, $user['id'], $memo, $order_type == 'groups' ? 'groups' : 'pay', implode(",", $orderIds));
                } else {
                    $result = self::money(-$price, $user['id'], '余额合并支付' . $order_type == 'groups' ? '拼团' : '商品' . '订单', $order_type == 'groups' ? 'groups' : 'pay', implode(",", $orderIds));
                }
                if ($order_type == 'groups') {
                    model('app\api\model\wanlshop\groups\Groups')->isUpdate()->saveAll($groups_list);
                    model('app\api\model\wanlshop\groups\Team')->saveAll($groups_team_list);
                }

                //dayin
                /*\think\Log::error("pay.print_before");
                $this->print($row['order_id']);

                //同步第三方
                //$order_sn = $model_order->where('id', $item)->value('order_no');
                \think\Log::error("pay.sync_before");
                $pay = \app\api\model\wanlshop\Pay::where('order_id', $row['order_id'])->find();
                \think\Log::error("pay.order_id:{$row['order_id']},pay_type:{$pay->pay_type}");

                $thrid = new Thirdplatform();
                $thrid->pay($pay->order_no, 4);

                Order::scoreHandle($row['order_id'], $row['user_id']);*/

                Db::commit();
            } catch (Exception $e) {
                Db::rollback();
                return ['code' => 10002, 'msg' => $e->getMessage()];
            }

            // 返回结果
            if ($result !== false) {
                return ['code' => 200, 'msg' => '成功', 'data' => []];
            } else {
                return ['code' => 10003, 'msg' => '支付异常'];
            }
            // 支付宝支付、更新数据均在回调中执行
        } else if ($this->type == 'alipay') {
            $data = [
                'out_trade_no' => $out_trade_no,
                'total_amount' => $price, //todo 上线改回实际价格
//                'total_amount' => 0.01,
                'subject' => $title
            ];

            try {
                $alipay = Pay::alipay(self::getConfig($this->type))->app($data);

                //dayin
                /*\think\Log::error("pay.print_before");
                $this->print($row['order_id']);

                //同步第三方
                //$order_sn = $model_order->where('id', $item)->value('order_no');
                \think\Log::error("pay.sync_before");
                $pay = \app\api\model\wanlshop\Pay::where('order_id', $row['order_id'])->find();
                \think\Log::error("pay.order_id:{$row['order_id']},pay_type:{$pay->pay_type}");

                $thrid = new Thirdplatform();
                $thrid->pay($pay->order_no, 4);

                Order::scoreHandle($row['order_id'], $row['user_id']);*/

                if ($this->method == 'app' || $this->method == 'wap') {
                    \think\Log::error('alipay支付参数：' . json_encode($alipay->getContent(), 256));
                    return ['code' => 200, 'msg' => '成功', 'data' => $alipay->getContent()];
                } else {
                    return ['code' => 200, 'msg' => '成功', 'data' => $alipay];
                }
            } catch (\Exception $e) {
                return ['code' => 10006, 'msg' => $e->getMessage()];
            }
            // 微信支付
        } else if ($this->type == 'wechat') {
            $data = [
                'out_trade_no' => $out_trade_no, // 订单号
                'body' => $title, // 标题
                'total_fee' => $price * 100 //付款金额 单位分
            ];
            if ($this->method == 'miniapp') {
                // 获取微信openid，前期版本仅可安全获取，后续版本优化登录逻辑
                $config = get_addon_config('wanlshop');
                $params = [
                    'appid' => $config['mp_weixin']['appid'],
                    'secret' => $config['mp_weixin']['appsecret'],
                    'js_code' => $this->code,
                    'grant_type' => 'authorization_code'
                ];
                $time = time();
                $result = Http::sendRequest("https://api.weixin.qq.com/sns/jscode2session", $params, 'GET');
                if ($result['ret']) {
                    $json = (array)json_decode($result['msg'], true);
                    $third = model('app\api\model\wanlshop\Third')->get(['platform' => 'weixin_open', 'openid' => $json['openid']]);
                    if (!$third) {
                        $third = model('app\api\model\wanlshop\Third');
                        // array_key_exists("unionid",$json)
                        if (isset($json['unionid'])) {
                            $third->unionid = $json['unionid'];
                            $third->openid = $json['openid'];
                        } else {
                            $third->openid = $json['openid'];
                        }
                        $third->access_token = $json['session_key'];
                        $third->expires_in = 7776000;
                        $third->logintime = $time;
                        $third->expiretime = $time + 7776000;
                        $third->user_id = $this->user_id;
                        $third->save();
                    }
                    $data['openid'] = $json['openid'];
                } else {
                    return ['code' => 10005, 'msg' => '获取微信openid失败，无法支付'];
                }
            } else if ($this->method == 'mp') {
                // 微信公众平台支付必有OPENID 1.1.2升级
                $third = model('app\api\model\wanlshop\Third')
                    ->where(['platform' => 'weixin_h5', 'user_id' => $this->user_id])
                    ->find();
                if ($third) {
                    $data['openid'] = $third['openid'];
                } else {
                    return ['code' => 10005, 'msg' => '获取微信openid失败，无法支付'];
                }
            }
            // 开始支付
            try {
                \think\Log::error("wechat pay:{$this->type},method:{$this->method},data:" . json_encode($data, 256));
                $wechat = Pay::wechat(self::getConfig($this->type))->{$this->method}($data);

                //dayin
                /*\think\Log::error("pay.print_before");
                $this->print($row['order_id']);

                //同步第三方
                //$order_sn = $model_order->where('id', $item)->value('order_no');
                \think\Log::error("pay.sync_before");
                $pay = \app\api\model\wanlshop\Pay::where('order_id', $row['order_id'])->find();
                \think\Log::error("pay.order_id:{$row['order_id']},pay_type:{$pay->pay_type}");

                $thrid = new Thirdplatform();
                $thrid->pay($pay->order_no, 4);

                Order::scoreHandle($row['order_id'], $row['user_id']);*/

                if ($this->method == 'app') {
                    \think\Log::error("wechat pay res :" . json_encode($wechat->getContent(), 256));
                    return ['code' => 200, 'msg' => '成功', 'data' => $wechat->getContent()];
                } else if ($this->method == 'wap') {
                    return ['code' => 200, 'msg' => '成功', 'data' => $wechat->getTargetUrl()];
                } else {
                    return ['code' => 200, 'msg' => '成功', 'data' => $wechat];
                }
            } catch (\Exception $e) {
                return ['code' => 10006, 'msg' => $this->type . '：' . $e->getMessage()];
            }
            // 百度支付
        } else if ($this->type == 'baidu') {
            try {

            } catch (\Exception $e) {
                return ['code' => 10006, 'msg' => $this->type . '：' . $e->getMessage()];
            }
            // QQ支付
        } else if ($this->type == 'qq') {
            try {

            } catch (\Exception $e) {
                return ['code' => 10006, 'msg' => $this->type . '：' . $e->getMessage()];
            }
            // 苹果支付
        } else if ($this->type == 'apple') {
            try {

            } catch (\Exception $e) {
                return ['code' => 10006, 'msg' => $this->type . '：' . $e->getMessage()];
            }
        } else {
            return ['code' => 10010, 'msg' => '未找到任何有效支付'];
        }
    }

    /**
     * 用户充值
     */
    public function recharge($price)
    {
        if ($this->user_id == 0) {
            return ['code' => 10001, 'msg' => '用户ID不存在'];
        }
        if ($price <= 0) {
            return ['code' => 10002, 'msg' => '充值金额不合法'];
        }
        // 充值订单号
        $pay_no = date("Ymdhis") . sprintf("%08d", $this->user_id) . mt_rand(1000, 9999);
        // 支付标题
        $title = '充值-' . $pay_no;
        // 生成一个订单
        $order = \app\api\model\wanlshop\RechargeOrder::create([
            'orderid' => $pay_no,
            'user_id' => $this->user_id,
            'amount' => $price,
            'payamount' => 0,
            'paytype' => $this->type,
            'ip' => $this->request->ip(),
            'useragent' => substr($this->request->server('HTTP_USER_AGENT'), 0, 255),
            'status' => 'created'
        ]);

        if ($this->type == 'alipay') {
            // 获取配置
            $payConfig = self::getConfig($this->type);
            $payConfig['notify_url'] = str_replace("notify", "notify_recharge", $payConfig['notify_url']);
            $data = [
                'out_trade_no' => $pay_no,
                'total_amount' => $price,
                'subject' => $title
            ];
            try {
                $alipay = Pay::alipay($payConfig)->{$this->method}($data);
                if ($this->method == 'app' || $this->method == 'wap') {
                    return ['code' => 200, 'msg' => '成功', 'data' => $alipay->getContent()];
                } else {
                    return ['code' => 200, 'msg' => '成功', 'data' => $alipay];
                }
                // 1.1.5升级 捕获异常
            } catch (\Exception $e) {
                return ['code' => 10006, 'msg' => $this->type . '：' . $e->getMessage()];
            }

            // 微信支付
        } else if ($this->type == 'wechat') {
            // 获取配置
            $payConfig = self::getConfig($this->type);
            $payConfig['notify_url'] = str_replace("notify", "notify_recharge", $payConfig['notify_url']);
            $data = [
                'out_trade_no' => $pay_no, // 订单号
                'body' => $title, // 标题
                'total_fee' => $price * 100 //付款金额 单位分
            ];
            if ($this->method == 'miniapp') {
                // 获取微信openid，前期版本仅可安全获取，后续版本优化登录逻辑
                $config = get_addon_config('wanlshop');
                $params = [
                    'appid' => $config['mp_weixin']['appid'],
                    'secret' => $config['mp_weixin']['appsecret'],
                    'js_code' => $this->code,
                    'grant_type' => 'authorization_code'
                ];
                $time = time();
                $result = Http::sendRequest("https://api.weixin.qq.com/sns/jscode2session", $params, 'GET');
                if ($result['ret']) {
                    $json = (array)json_decode($result['msg'], true);
                    $third = model('app\api\model\wanlshop\Third')->get(['platform' => 'weixin_open', 'openid' => $json['openid']]);
                    if (!$third) {
                        $third = model('app\api\model\wanlshop\Third');
                        if (isset($json['unionid'])) {
                            $third->unionid = $json['unionid'];
                            $third->openid = $json['openid'];
                        } else {
                            $third->openid = $json['openid'];
                        }
                        $third->access_token = $json['session_key'];
                        $third->expires_in = 7776000;
                        $third->logintime = $time;
                        $third->expiretime = $time + 7776000;
                        $third->user_id = $this->user_id;
                        $third->save();
                    }
                    $data['openid'] = $json['openid'];
                } else {
                    return ['code' => 10005, 'msg' => '获取微信openid失败，无法支付'];
                }
            } else if ($this->method == 'mp') {
                // 微信公众平台支付必有OPENID 1.1.2升级
                $third = model('app\api\model\wanlshop\Third')
                    ->where(['platform' => 'weixin_h5', 'user_id' => $this->user_id])
                    ->find();
                if ($third) {
                    $data['openid'] = $third['openid'];
                } else {
                    return ['code' => 10005, 'msg' => '获取微信openid失败，无法支付'];
                }
            }
            // 开始支付
            try {
                $wechat = Pay::wechat($payConfig)->{$this->method}($data);
                if ($this->method == 'app') {
                    return ['code' => 200, 'msg' => '成功', 'data' => $wechat->getContent()];
                } else if ($this->method == 'wap') {
                    return ['code' => 200, 'msg' => '成功', 'data' => $wechat->getTargetUrl()];
                } else {
                    return ['code' => 200, 'msg' => '成功', 'data' => $wechat];
                }
                // 1.1.5升级 捕获异常
            } catch (\Exception $e) {
                return ['code' => 10006, 'msg' => $this->type . '：' . $e->getMessage()];
            }
            // 百度支付
        } else if ($this->type == 'baidu') {
            try {

            } catch (\Exception $e) {
                return ['code' => 10006, 'msg' => $this->type . '：' . $e->getMessage()];
            }
            // QQ支付
        } else if ($this->type == 'qq') {
            try {

            } catch (\Exception $e) {
                return ['code' => 10006, 'msg' => $this->type . '：' . $e->getMessage()];
            }
            // 苹果支付
        } else if ($this->type == 'apple') {
            try {

            } catch (\Exception $e) {
                return ['code' => 10006, 'msg' => $this->type . '：' . $e->getMessage()];
            }
        } else {
            return ['code' => 10010, 'msg' => '未找到任何有效支付'];
        }
    }

    /**
     * 支付回调
     */
    public function notify()
    {
        $wanlpay = Pay::{$this->type}(self::getConfig($this->type));
        try {
            $result = $wanlpay->verify();
            \think\Log::error("notify params:" . json_encode($result, JSON_UNESCAPED_UNICODE));
            // 查询支付集
            $payOutTrade = model('app\api\model\wanlshop\PayOutTrade')
                ->where(['out_trade_no' => $result['out_trade_no']])
                ->find();
            // 查询订单是否存在
            $pay = model('app\api\model\wanlshop\Pay')
                ->where('id', 'in', $payOutTrade['pay_id'])
                ->where('pay_state', 'neq', '1')
                ->select();
            if (!$pay) {
                return ['code' => 10001, 'msg' => '网络异常'];
            }
            // 1.0.8升级 拼团订单
            $order_type = $pay[0]['type'];
            if ($order_type == 'groups') {
                $model_order = model('app\api\model\wanlshop\groups\Order');
                $model_order_goods = model('app\api\model\wanlshop\groups\OrderGoods');
                $model_goods = model('app\api\model\wanlshop\groups\Goods');
            } else {
                $model_order = model('app\api\model\wanlshop\Order');
                $model_order_goods = model('app\api\model\wanlshop\OrderGoods');
                $model_goods = model('app\api\model\wanlshop\Goods');
            }
            $trade_no = '';
            // 支付类型
            $pay_type = 8;
            $user_id = 0;
            $order_no = [];
            // 总价格
            $price = 0;
            // 主要用于日志
            foreach ($pay as $row) {
                // $price += $row['price']; 1.0.8 升级
                $price = bcadd($price, $row['price'], 2); // 总价格
                // 订单集
                $order_no[] = $row['order_no'];
                $user_id = $row['user_id'];
            }
            // -----------------------------判断订单是否合法-----------------------------
            $config = get_addon_config('wanlshop');
            // 支付宝
            if ($this->type == 'alipay') {
                // 判断状态
                if (in_array($result['trade_status'], ['TRADE_SUCCESS', 'TRADE_FINISHED'])) {
                    // 判断金额
                    if ($price != $result['total_amount']) {
                        return ['code' => 10002, 'msg' => '支付金额不合法'];
                    }
                    // 判断appid
                    if ($config['sdk_alipay']['app_id'] != $result['app_id']) {
                        return ['code' => 10003, 'msg' => 'APPID不合法'];
                    }
                } else {
                    return ['code' => 500, 'msg' => '支付回调失败'];
                }
                // 回调支付
                $pay_type = 2; // 支付类型:0=余额支付,1=微信支付,2=支付宝支付
                $pay_name = '支付宝';
                $trade_no = $result['trade_no'];
            } else if ($this->type == 'wechat') {
                // 判断状态
                if ($result['result_code'] == 'SUCCESS') {
                    // 判断金额
                    if ($price != ($result['total_fee'] / 100)) {
                        return ['code' => 10002, 'msg' => '支付金额不合法'];
                    }
                    // 判断商家ID
                    if ($config['sdk_qq']['mch_id'] != $result['mch_id']) {
                        return ['code' => 10004, 'msg' => '商户不合法'];
                    }
                    // H5微信支付
                    if ($result['trade_type'] == 'MWEB') {
                        if ($config['sdk_qq']['gz_appid'] != $result['appid']) {
                            return ['code' => 10005, 'msg' => '支付类型 ' . $result['trade_type'] . ' 不合法'];
                        }
                    }
                    // 小程序支付
                    if ($result['trade_type'] == 'JSAPI') {
                        if ($config['mp_weixin']['appid'] != $result['appid']) {
                            if ($config['sdk_qq']['gz_appid'] != $result['appid']) {
                                return ['code' => 10006, 'msg' => '支付APPID不合法'];
                            }
                        }
                    }
                    // App支付
                    if ($result['trade_type'] == 'APP') {
                        if ($config['sdk_qq']['wx_appid'] != $result['appid']) {
                            return ['code' => 10007, 'msg' => '支付类型 ' . $result['trade_type'] . ' 不合法'];
                        }
                    }
                } else {
                    return ['code' => 500, 'msg' => '支付回调失败'];
                }
                // 回调支付
                $pay_type = 1; // 支付类型:0=余额支付,1=微信支付,2=支付宝支付
                $pay_name = '微信';
                $trade_no = $result['transaction_id'];
            }
            // -----------------------------支付成功，修改订单-----------------------------
            $order_list = [];
            $pay_list = [];
            // 拼团列表
            $groups_list = [];
            // 拼团列表
            $groups_team_list = [];
            foreach ($pay as $row) {
                $isAlone = false; // 拼团订单一般是单订单，暂可以这样操作
                $groups_state = 'start'; // 拼团状态
                foreach ($model_order_goods->where('order_id', $row['order_id'])->select() as $goods) {
                    if ($order_type == 'groups' && !empty($goods['group_type'])) {
                        if ($goods['group_type'] == 'alone') {
                            $isAlone = true;
                        } else {
                            // 查询团ID
                            $groups = model('app\api\model\wanlshop\groups\Groups')
                                ->where(['group_no' => $goods['group_no']])
                                ->find();
                            // 判断是否超团
                            $groups_team = model('app\api\model\wanlshop\groups\Team')
                                ->where(['group_no' => $goods['group_no']])
                                ->select();
                            // 已拼团总数量
                            $groups_team_count = count($groups_team);
                            if ($groups_team_count >= $groups['people_num'] || $groups['join_num'] >= $groups['people_num']) {
                                throw new Exception('参与拼单失败，拼团已完成');
                            }
                            // 判断是否具备成团条件
                            if (($groups['people_num'] - $groups_team_count) <= 1 || ($groups['people_num'] - $groups['join_num']) <= 1) {
                                $groups_state = 'success';
                                //调整其他拼团订单
                                // 订单状态:1=待支付,2=待成团,3=待发货,4=待收货,5=待评论,6=已完成,7=已取消
                                foreach ($groups_team as $team) {
                                    $order_list[] = ['id' => $team['order_id'], 'state' => 3, 'groupstime' => time()];
                                }
                            }
                            // 拼团状态: ready=准备中,start=拼团中,success=已成团,fail=拼团失败,auto=自动成团
                            $groups_list[] = [
                                'id' => $groups['id'],
                                'join_num' => $groups['join_num'] + 1,
                                'state' => $groups_state
                            ];
                            $groups_team_list[] = [
                                'user_id' => $user_id, // 1.0.9升级
                                'shop_id' => $goods['shop_id'],
                                'group_no' => $goods['group_no'],
                                'order_id' => $goods['order_id'],
                                'order_goods_id' => $goods['id']
                            ];
                        }
                    }
                    // 新增付款人数、新增销量
                    $model_goods->where('id', $goods['goods_id'])->inc('payment')->inc('sales', $goods['number'])->update();
                }
                // 订单列表
                if ($groups_state === 'success') {
                    $order_list[] = ['id' => $row['order_id'], 'state' => 3, 'paymenttime' => time(), 'groupstime' => time()];
                } else {
                    $order_list[] = ['id' => $row['order_id'], 'state' => $isAlone ? 3 : 2, 'paymenttime' => time()];
                }
                // 支付列表 1.0.9升级
                $pay_list[] = [
                    'id' => $row['id'],
                    'trade_no' => $trade_no, // 第三方交易号
                    'pay_type' => $pay_type, // 支付类型:0=余额支付,1=微信支付,2=支付宝支付
                    'pay_state' => 1, // 支付状态 (支付回调):0=未支付,1=已支付,2=已退款
                    'total_amount' => $price, // 总金额
                    'actual_payment' => $row['price'], // 实际支付
                    'notice' => json_encode($result)
                ];

                //打印 同步订单 积分处理
                \think\Log::error("notify:打印 同步订单 积分处理");
                $res = $this->extHandle($row['order_id'], $row['user_id']);
                if ($res !== true) {
                    \think\Log::error("notify error:$res");
                    throw new Exception($res);
                }
            }
            // 更新支付列表
            model('app\api\model\wanlshop\Pay')->saveAll($pay_list);
            // 更新订单列表
            $model_order->saveAll($order_list);
            // 支付日志
            model('app\common\model\MoneyLog')->create([
                'user_id' => $user_id,
                'money' => -$price, // 操作金额
                'memo' => $pay_name . '支付' . $order_type == 'groups' ? '拼团' : '商城' . '订单', // 备注
                'type' => $order_type == 'groups' ? 'groups' : 'pay', // 类型
                'service_ids' => implode(",", $order_no) // 业务ID
            ]);
            \think\Log::error('Wanlpay notify', $result->all());
            if ($order_type == 'groups') {
                model('app\api\model\wanlshop\groups\Groups')->isUpdate()->saveAll($groups_list);
                model('app\api\model\wanlshop\groups\Team')->saveAll($groups_team_list);
            }
            // 1.1.5升级 捕获异常
        } catch (\Exception $e) {
            return ['code' => 10008, 'msg' => $e->getMessage()];
        }
        // 返回给支付接口
        return ['code' => 200, 'msg' => $wanlpay->success()->send()];
    }

    /**
     * 充值支付回调
     */
    public function notify_recharge()
    {
        $wanlpay = Pay::{$this->type}(self::getConfig($this->type));
        try {
            $result = $wanlpay->verify();
            // 查询订单是否存在
            $order = model('app\api\model\wanlshop\RechargeOrder')
                ->where(['orderid' => $result['out_trade_no']])
                ->find();
            if (!$order) {
                return ['code' => 10001, 'msg' => '支付订单不存在'];
            } else {
                if ($order['status'] == 'paid') {
                    return ['code' => 10007, 'msg' => '订单已经支付过'];
                }
            }
            $memo = '';
            $trade_no = '';
            // -----------------------------判断订单是否合法-----------------------------
            $config = get_addon_config('wanlshop');
            // 支付宝
            if ($this->type == 'alipay') {
                // 判断状态
                if (in_array($result['trade_status'], ['TRADE_SUCCESS', 'TRADE_FINISHED'])) {
                    // 判断金额
                    if ($order['amount'] != $result['total_amount']) {
                        return ['code' => 10002, 'msg' => '支付金额不合法'];
                    }
                    // 判断appid
                    if ($config['sdk_alipay']['app_id'] != $result['app_id']) {
                        return ['code' => 10003, 'msg' => 'APPID不合法'];
                    }
                } else {
                    return ['code' => 500, 'msg' => '支付回调失败'];
                }
                $memo = '支付宝充值';
                $trade_no = $result['trade_no'];
            } else if ($this->type == 'wechat') {
                // 判断状态
                if ($result['result_code'] == 'SUCCESS') {
                    // 判断金额
                    if ($order['amount'] != ($result['total_fee'] / 100)) {
                        return ['code' => 10002, 'msg' => '支付金额不合法'];
                    }
                    // 判断商家ID
                    if ($config['sdk_qq']['mch_id'] != $result['mch_id']) {
                        return ['code' => 10004, 'msg' => '商户不合法'];
                    }
                    // H5微信支付
                    if ($result['trade_type'] == 'MWEB') {
                        if ($config['sdk_qq']['gz_appid'] != $result['appid']) {
                            return ['code' => 10005, 'msg' => '支付类型 ' . $result['trade_type'] . ' 不合法'];
                        }
                    }
                    // 小程序支付
                    if ($result['trade_type'] == 'JSAPI') {
                        if ($config['mp_weixin']['appid'] != $result['appid']) {
                            if ($config['sdk_qq']['gz_appid'] != $result['appid']) {
                                return ['code' => 10006, 'msg' => '支付APPID不合法'];
                            }
                        }
                    }
                    // App支付
                    if ($result['trade_type'] == 'APP') {
                        if ($config['sdk_qq']['wx_appid'] != $result['appid']) {
                            return ['code' => 10007, 'msg' => '支付类型 ' . $result['trade_type'] . ' 不合法'];
                        }
                    }
                } else {
                    return ['code' => 500, 'msg' => '支付回调失败'];
                }
                $memo = '微信充值';
                $trade_no = $result['transaction_id'];
            }
            // -----------------------------支付成功，修改订单-----------------------------
            if ($order['status'] == 'created') {
                $order->memo = $trade_no;
                $order->payamount = $order['amount']; // 上面已经判断过金额，可以直接使用
                $order->paytime = time();
                $order->status = 'paid';
                $order->save();
                // 更新用户金额
                self::money(+$order['amount'], $order['user_id'], $memo, 'recharge', $order['id']);
            }
            \think\Log::error('Wanlpay notify', $result->all());
            // 1.1.5升级 捕获异常
        } catch (\Exception $e) {
            return ['code' => 10008, 'msg' => $e->getMessage()];
        }
        // 返回给支付接口
        return ['code' => 200, 'msg' => $wanlpay->success()->send()];
    }

    /**
     * 退款回调
     */
    public function notify_refund()
    {
        $wanlpay = Pay::{$this->type}(self::getConfig($this->type));
        try {
            $result = $wanlpay->verify(null, true);
            // 支付宝
            if ($this->type == 'wechat') {
                $type_text = '微信支付';
                $money = bcdiv($result['refund_fee'], 100, 2);
                $pay_no = $result['out_refund_no'];
            } else if ($this->type == 'alipay') {
                $type_text = '支付宝支付';
                $money = $result['refund_amount'];
                $pay_no = $result['body'];
            }
            // 查询支付集
            // $payOutTrade = model('app\api\model\wanlshop\PayOutTrade')
            // 	->where('out_trade_no', 'eq', $result['out_trade_no'])
            // 	->find();
            // 查询订单是否存在
            $pay = model('app\api\model\wanlshop\Pay')
                ->where('pay_no', 'eq', $pay_no)
                ->where('pay_state', 'eq', '1')
                ->find();
            if ($pay) {
                $refund = model('app\api\model\wanlshop\Refund')
                    ->where([
                        'user_id' => $pay['user_id'],
                        'order_pay_id' => $pay['id'],
                        'order_id' => $pay['order_id'],
                        'order_type' => $pay['type']
                    ])
                    ->find();
                // 判断退款是否存在,退款状态是否第三方退款中状态
                if ($refund) {
                    if ($refund['state'] == '3' || $refund['state'] == '7') {
                        // 判断退款金额
                        if (bccomp($money, $refund['price'], 4) == 0) {
                            // 更新商品状态
                            $this->setOrderGoodsState(3, $refund['goods_ids'], $refund['order_type']);
                            // 更新订单状态
                            $this->setRefundState($refund['order_id'], $refund['order_type']);

                            // 写入日志
                            $this->refundLog($pay['user_id'], $refund['id'], $type_text . '退款处理成功，订单金额￥' . $refund['price'] . '元已到账');
                            // 推送开始
                            $this->pushRefund($refund['id'], $refund['order_id'], $refund['goods_ids'], '退款成功', $refund['order_type']);
                            // 更新退款
                            $refund->allowField(true)->save(['state' => 4, 'notice' => json_encode($result), 'completetime' => time()]);
                        } else {
                            // 写入日志
                            $this->refundLog($pay['user_id'], $refund['id'], $type_text . '退款订单异常，订单金额￥' . $refund['price'] . '元，实际退款金额￥' . $money . '元');
                            // 推送开始
                            $this->pushRefund($refund['id'], $refund['order_id'], $refund['goods_ids'], $type_text . '退款金额不匹配，退款失败', $refund['order_type']);
                            // 更新退款
                            $refund->allowField(true)->save(['state' => 8, 'notice' => json_encode($result), 'refuse_content' => $type_text . '退款失败，金额不匹配，请联系管理员']);
                        }
                    } else {
                        // 写入日志
                        $this->refundLog($pay['user_id'], $refund['id'], $type_text . '退款订单异常');
                        // 推送开始
                        $this->pushRefund($refund['id'], $refund['order_id'], $refund['goods_ids'], $type_text . '退款订单异常，退款失败', $refund['order_type']);
                        // 更新退款
                        $refund->allowField(true)->save(['state' => 8, 'notice' => json_encode($result), 'refuse_content' => $type_text . '退款订单不存在，请联系管理员']);
                    }
                }
            } else {
                return ['code' => 10001, 'msg' => '支付订单不存在'];
            }
        } catch (\Exception $e) {
            // 错误逻辑
            return ['code' => 10008, 'msg' => $e->getMessage()];
        }
        // 返回给支付接口
        return ['code' => 200, 'msg' => $wanlpay->success()->send()];
    }


    /**
     * 第三方退款
     * @param int $money 金额
     * @param int $pay_id 会员ID
     * @1.1.2升级 ~ 1.1.5升级
     */
    public function refund($refund_id, $money, $pay_id)
    {
        $type = '';
        $pay = model('app\api\model\wanlshop\Pay')->get($pay_id);
        if ($pay && $pay['pay_state'] == 1 && $pay['pay_type'] != 0) {
            // 1.1.3升级
            $trade = model('app\api\model\wanlshop\PayOutTrade')
                ->where([['EXP', Db::raw('FIND_IN_SET(' . $pay['id'] . ', pay_id)')]])
                ->find();
            if (!$trade) {
                return ['code' => 10009, 'msg' => '没有找到商户订单号'];
            }
            if ($pay['pay_type'] == 1) {
                $type = 'wechat';
                $type_text = '微信';
                // 退款订单
                $order['out_trade_no'] = $trade['out_trade_no'];
                $order['out_refund_no'] = $pay['pay_no']; //商家订单号
                // 分批退款
                if (count(explode(',', $trade['pay_id'])) > 1) {
                    // 总金额
                    $order['total_fee'] = bcmul(model('app\api\model\wanlshop\Pay')
                        ->where('id', 'in', $trade['pay_id'])
                        ->sum('price'), 100, 0);
                } else {
                    $order['total_fee'] = bcmul($pay['price'], 100, 0); // 订单金额
                }
                $order['refund_fee'] = bcmul($money, 100, 0);
                $order['refund_desc'] = '商城订单（订单号：' . $pay['order_no'] . '）退款' . $type_text . '账户￥' . $money . '元。';
                $notice = json_decode($pay['notice'], true);
                switch ($notice['trade_type']) {
                    case 'JSAPI':
                        $order['type'] = 'miniapp';
                        break;
                    case 'APP':
                        $order['type'] = 'app';
                        break;
                }
            } else if ($pay['pay_type'] == 2) {
                $type = 'alipay';
                $type_text = '支付宝';
                // 1.1.3升级
                $order['out_trade_no'] = $trade['out_trade_no'];
                $order['refund_amount'] = $money; //退款金额
                $order['refund_reason'] = '商城订单（订单号：' . $pay['order_no'] . '）退款买家' . $type_text . '账户￥' . $money . '元。'; //退款原因说明
                // 分批退款
                if (count(explode(',', $trade['pay_id'])) > 1) {
                    $order['out_request_no'] = $refund_id; //退款请求号
                }
            }
            // 退款 1.1.5升级
            try {
                $payConfig = self::getConfig($type);
                $payConfig['notify_url'] = str_replace("notify", "notify_refund", $payConfig['notify_url']);
                $wanlpay = Pay::{$type}($payConfig)->refund($order);
                $result = false;
                // 注意，接口中result_code=SUCCESS，仅代表本次退款请求成功，不代表退款成功
                if ($type == 'wechat' && $wanlpay->result_code == 'SUCCESS') {
                    // 关于微信退款:
                    // 微信退款不提供退款结果,仅返回退款请求成功,所以必须$result=true

                    // 通过回调来获取结果
                    $result = true;
                }
                // 注意，接口中code=10000，仅代表本次退款请求成功，不代表退款成功
                if ($type == 'alipay' && $wanlpay->code == '10000') {
                    // fund_change = Y，代表退款成功，支付宝文档《如何判断退款是否成功》，https://opendocs.alipay.com/support/01rawa
                    if ($wanlpay->fund_change == 'Y') {
                        return ['code' => 0, 'msg' => 'OK', 'data' => [
                            'money' => $money,
                            'user_id' => $pay['user_id'],
                            'type_text' => $type_text,
                            'refund_id' => $refund_id
                        ]];
                    } else {
                        // 通过回调来获取结果
                        // $result = true;

                        // 关于支付宝退款：
                        // 因测试订单时请求的均为 fund_change=Y 状态，即代表退款成功，可同步退款成功,以上注释支付宝文档《如何判断退款是否成功》
                        // 返回结果中的notify_url为配置的参数 也为notify_refund()方法,
                        // 但，实际服务器接收到异步回调为 notify()方法 且notify()中接受到的 TRADE_CLOSED交易状态为 "交易关闭"
                        // 目前等待支付宝进一步反馈，我们判断因为退款已成功fund_change=Y，所以返回notify() 为交易关闭
                        // 即使可以通过回调,可没有 同步fund_change=Y 状态安全可靠，已下

                        // 当前最佳最合理安全方案:
                        // 1.当 提交退款请求,且fund_change=Y同步完成退款(否则会出现已经给用户支付宝退款,但没有扣用户本地余额,会存在一定风险)
                        // 2.如果 极少数订单出现fund_change=N 时 code=10010中断第三方支付,使金额转到商城余额在手动提现，可避免任何风险产生
                        return ['code' => 10010, 'msg' => '提交退款未同步退款成功'];
                    }
                }
                if ($result) {
                    return ['code' => 200, 'msg' => 'OK', 'data' => [
                        'money' => $money,
                        'user_id' => $pay['user_id'],
                        'type_text' => $type_text,
                        'refund_id' => $refund_id
                    ]];
                } else {
                    return ['code' => 10009, 'msg' => '退款失败'];
                }
            } catch (\Exception $e) {
                return ['code' => 10008, 'msg' => $e->getMessage()];
            }
        }
    }

    /**
     * 变更会员余额
     * @param int $money 余额
     * @param int $user_id 会员ID
     * @param string $memo 备注
     * @param string $type 类型
     * @param string $ids 业务ID
     */
    public static function money($money, $user_id, $memo, $type = '', $ids = '')
    {
        $user = model('app\common\model\User')->get($user_id);
        if ($user && $money != 0) {
            $before = $user->money;
            $after = function_exists('bcadd') ? bcadd($user->money, $money, 2) : $user->money + $money;
            //更新会员信息
            $user->save(['money' => $after]);
            //写入日志
            $row = model('app\common\model\UserFinanceLog')->create([
                'user_id' => $user_id,
                'type' => 'money',
                'flag' => $money > 0 ? 'add' : 'reduce',
                'value' => abs($money), // 操作金额
                'before' => $before, // 原金额
                'after' => $after, // 增加后金额
                'event' => $type, // 类型
                'rel_id' => $ids, // 业务ID
                'remark' => $memo, // 备注
                'status' => 'succeed', // 审核状态
                'createtime' => time(),
                'updatetime' => time()
            ]);
            return $row;
        } else {
            return ['code' => 500, 'msg' => '变更金额失败'];
        }
    }


    /**
     * 推送退款消息（方法内使用）
     *
     * @param string refund_id 订单ID
     * @param string order_id 订单ID
     * @param string goods_id 订单ID
     * @param string title 标题
     */
    private function pushRefund($refund_id = 0, $order_id = 0, $goods_id = 0, $title = '', $order_type = 'goods')
    {
        if ($order_type === 'groups') {
            $orderModel = model('app\index\model\wanlshop\groups\Order');
            $orderGoodsModel = model('app\index\model\wanlshop\groups\OrderGoods');
        } else {
            $orderModel = model('app\index\model\wanlshop\Order');
            $orderGoodsModel = model('app\index\model\wanlshop\OrderGoods');
        }
        $order = $orderModel->get($order_id);
        $goods = $orderGoodsModel->get($goods_id);
        $msg = [
            'user_id' => $order['user_id'], // 推送目标用户
            'shop_id' => $order['shop_id'],
            'title' => $title,  // 推送标题
            'image' => $goods['image'], // 推送图片
            'content' => '您申请退款的商品 ' . (mb_strlen($goods['title'], 'utf8') >= 25 ? mb_substr($goods['title'], 0, 25, 'utf-8') . '...' : $goods['title']) . ' ' . $title,
            'type' => 'order',  // 推送类型
            'modules' => $order_type === 'groups' ? 'groupsrefund' : 'refund',  // 模块类型
            'modules_id' => $refund_id,  // 模块ID
            'come' => '订单' . $order['order_no'] // 来自
        ];
        $this->wanlchat->send($order['user_id'], $msg);
        $notice = model('app\index\model\wanlshop\Notice');
        $notice->data($msg);
        $notice->allowField(true)->save();
    }

    /**
     * 更新订单商品状态（方法内使用）
     *
     * @ApiSummary  (WanlShop 更新订单商品状态)
     * @ApiMethod   (POST)
     *
     * @param string $status 状态
     * @param string $goods_id 商品ID
     */
    private function setOrderGoodsState($status = 0, $goods_id = 0, $order_type = 'goods')
    {
        if ($order_type === 'groups') {
            $orderGoodsModel = model('app\index\model\wanlshop\groups\OrderGoods');
        } else {
            $orderGoodsModel = model('app\index\model\wanlshop\OrderGoods');
        }
        return $orderGoodsModel->save(['refund_status' => $status], ['id' => $goods_id]);
    }


    /**
     * 修改订单状态（方法内使用） 1.0.5升级
     *
     * @ApiSummary  (WanlShop 修改订单状态)
     * @ApiMethod   (POST)
     *
     * @param string $id 订单ID
     */
    private function setRefundState($order_id = 0, $order_type = 'goods')
    {
        if ($order_type === 'groups') {
            $orderModel = model('app\index\model\wanlshop\groups\Order');
            $orderGoodsModel = model('app\index\model\wanlshop\groups\OrderGoods');
        } else {
            $orderModel = model('app\index\model\wanlshop\Order');
            $orderGoodsModel = model('app\index\model\wanlshop\OrderGoods');
        }
        $list = $orderGoodsModel
            ->where(['order_id' => $order_id])
            ->select();
        $refundStatusCount = 0;
        foreach ($list as $row) {
            if ($row['refund_status'] == 3) $refundStatusCount += 1;
        }
        // 如果订单下所有商品全部退款完毕则关闭订单
        if (count($list) == $refundStatusCount) {
            $orderModel->save(['state' => 7], ['id' => $order_id]);
            return true;
        }
        return false;
    }

    /**
     * 退款日志（方法内使用）
     *
     * @ApiSummary  (WanlShop 退款日志)
     * @ApiMethod   (POST)
     *
     * @param string $user_id 用户ID
     * @param string $refund_id 退款ID
     * @param string $content 日志内容
     * @param string $type 退款状态:0=买家,1=卖家,2=官方,3=系统
     */
    private function refundLog($user_id = 0, $refund_id = 0, $content = '', $type = 3)
    {
        return model('app\index\model\wanlshop\RefundLog')->allowField(true)->save([
            'user_id' => $user_id,
            'refund_id' => $refund_id,
            'type' => $type,
            'content' => $content
        ]);
    }


    /**
     * 获取配置 1.1.2升级
     * @param string $type 支付类型
     * @return array|mixed
     */
    private function getConfig($type)
    {
        $config = get_addon_config('wanlshop');
        $pay_config = [];
        if ($type == 'alipay') {
            $pay_config = [
                'app_id' => $config['sdk_alipay']['app_id'],
                'notify_url' => $config['ini']['appurl'] . $config['sdk_alipay']['notify_url'],
                //'return_url' => $config['ini']['appurl'] . $config['sdk_alipay']['return_url'],
                'private_key' => $config['sdk_alipay']['private_key'],
                'log' => [
                    'file' => LOG_PATH . 'wanlpay' . DS . $type . '-' . date("Y-m-d") . '.log',
                    'level' => 'debug', // todo 建议生产环境等级调整为 info，开发环境为 debug
                    'type' => 'single', // optional, 可选 daily.
                    'max_file' => 30, // optional, 当 type 为 daily 时有效，默认 30 天
                ],
                'http' => [
                    'timeout' => 5.0,
                    'connect_timeout' => 5.0
                ],
            ];
            if (isset($config['sdk_alipay']['app_cert_public_key']) && substr($config['sdk_alipay']['app_cert_public_key'], 0, 8) == '/addons/') {
                $pay_config['app_cert_public_key'] = ROOT_PATH . str_replace('/', DS, substr($config['sdk_alipay']['app_cert_public_key'], 1));
            }
            if (isset($config['sdk_alipay']['alipay_root_cert']) && substr($config['sdk_alipay']['alipay_root_cert'], 0, 8) == '/addons/') {
                $pay_config['alipay_root_cert'] = ROOT_PATH . str_replace('/', DS, substr($config['sdk_alipay']['alipay_root_cert'], 1));
            }
            if (isset($config['sdk_alipay']['ali_public_key']) && (Str::endsWith($config['sdk_alipay']['ali_public_key'], '.crt') || Str::endsWith($config['sdk_alipay']['ali_public_key'], '.pem'))) {
                $pay_config['ali_public_key'] = ROOT_PATH . str_replace('/', DS, substr($config['sdk_alipay']['ali_public_key'], 1));
            }
        } else if ($type == 'wechat') {
            $pay_config = [
                'appid' => $config['sdk_qq']['wx_appid'], // APP APPID
//                'app_id' => $config['sdk_qq']['gz_appid'], // 公众号 APPID
//                'miniapp_id' => $config['mp_weixin']['appid'], // 小程序 APPID
                'mch_id' => $config['sdk_qq']['mch_id'],
                'key' => $config['sdk_qq']['key'],
                'notify_url' => $config['ini']['appurl'] . $config['sdk_qq']['notify_url'],
                // 1.0.8升级 回调 https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_4
                'return_url' => $config['h5']['domain'] . ($config['h5']['router_mode'] == 'hash' ? '/#' : '') . '/pages/page/success?type=pay',
                'log' => [
                    'file' => LOG_PATH . 'wanlpay' . DS . $type . '-' . date("Y-m-d") . '.log',
                    'level' => 'debug', // 建议生产环境等级调整为 info，开发环境为 debug
                    'type' => 'single', // optional, 可选 daily.
                    'max_file' => 30, // optional, 当 type 为 daily 时有效，默认 30 天
                ],
                'http' => [
                    'timeout' => 5.0,
                    'connect_timeout' => 5.0,
                    // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
                ],
            ];
            if (isset($config['sdk_qq']['cert_client']) && substr($config['sdk_qq']['cert_client'], 0, 8) == '/addons/') {
                $pay_config['cert_client'] = ROOT_PATH . str_replace('/', DS, substr($config['sdk_qq']['cert_client'], 1));
            }
            if (isset($config['sdk_qq']['cert_key']) && substr($config['sdk_qq']['cert_key'], 0, 8) == '/addons/') {
                $pay_config['cert_key'] = ROOT_PATH . str_replace('/', DS, substr($config['sdk_qq']['cert_key'], 1));
            }
        }
        return $pay_config;
    }

    public function transfer($order_no, $amount, $account, $name)
    {
        $order = [
            'out_biz_no' => $order_no,
            'trans_amount' => $amount,
            'product_code' => 'TRANS_ACCOUNT_NO_PWD',
            'biz_scene' => 'DIRECT_TRANSFER',
            'payee_info' => [
                'identity' => $account,
                'identity_type' => 'ALIPAY_LOGON_ID',
                'name' => $name,
            ],
        ];
        return Pay::alipay(self::getConfig($this->type))->transfer($order);
    }

    public function print($id)
    {
        \think\Log::error("打印：$id");
        $this->model = new \app\admin\model\uniprint\Printer;
        $this->configs = get_addon_config('uniprint');
        $config = new \App\Config\YlyConfig($this->configs['yilianyun']['appid'], $this->configs['yilianyun']['appsecret']);
        \think\Log::error("打印：get_config");

        // 获取token token永不过期
        $uniprint = get_addon_config('uniprint');
        if (empty($uniprint['yilianyun']['access_token'])) {
            $client = new \App\Oauth\YlyOauthClient($config);
            $token = $client->getToken();   //若是开放型应用请传授权码code
            $uniprint['yilianyun']['access_token'] = $token->access_token;
            set_addon_config('uniprint', $uniprint);
        }
        \think\Log::error("打印：get_token");

        $order = \app\admin\model\wanlshop\Order::where('id', $id)->find();
        $shop = Shop::where('id', $order->shop_id)->value('shopname');
        $goods = OrderGoods::where('order_id', $order->id)->select();
        $pay = \app\admin\model\wanlshop\Pay::where('order_id', $order->id)->find();
        $user = User::where('id', $order->user_id)->find();
        $address = Address::where('id', $order->address_id)->find();
        \think\Log::error("打印：get_models");
        //调取文本打印
        $content = "<FS2><center>**东火木**</center></FS2>";
        $content .= str_repeat('.', 32);
        $content .= "<FS2><center>--在线支付--</center></FS2>";
        $content .= "<FS><center>$shop</center></FS>";
        $content .= "订单时间:" . date("Y-m-d H:i", $order->createtime) . "\n";
        $content .= "订单编号:$order->order_no \n";
        $content .= str_repeat('*', 14) . "商品" . str_repeat("*", 14);
        $content .= "<table>";
        foreach ($goods as $item) {
            $content .= "<tr><td>{$item['title']}</td><td>{$item['difference']}</td><td>{$item['price']}</td><td>{$item['number']}</td><td>{$item['actual_payment']}</td></tr>";
        }
        $content .= "</table>";
        $content .= str_repeat('.', 32);
        $content .= "应支付金额:￥ {$pay->price} \n";
        $content .= "订单金额:￥ {$pay->order_price} \n";
        if ($pay->freight_price > 0) $content .= "快递金额:￥ {$pay->freight_price} \n";
        if ($pay->coupon_price > 0) $content .= "优惠券金额:￥ {$pay->coupon_price} \n";
        if ($pay->score_price > 0) $content .= "积分抵扣价格:￥ {$pay->score_price} \n";
        if ($pay->oldstaff_price > 0) $content .= "旧物抵扣金额:￥ {$pay->oldstaff_price} \n";
        if ($pay->system_price > 0) $content .= "系统优惠金额:￥ {$pay->system_price} \n";
        if ($pay->invoice_price > 0) $content .= "发票抵扣金额:￥ {$pay->invoice_price} \n";

        $content .= str_repeat('*', 32);
//        $content .= "订单总价:￥ {$pay->actual_payment} \n";
        $content .= str_repeat('.', 32);
        $content .= "用户昵称:$user->nickname \n";
        $content .= "手机号:$user->mobile \n";
        $content .= "地址:{$address->formatted_address}{$address->address}{$address->address_name} \n";
        $content .= "<FS2><center>** 完**</center></FS2>";
        \think\Log::error("打印：new PrintService");
        $print = new PrintService($uniprint['yilianyun']['access_token'], $config);
        $data = $print->index('4004769293', $content, '55044541');
        \think\Log::error("打印：content:" . $content . ",res:" . json_encode($data));
    }

    public function extHandle($oid, $uid)
    {
        \think\Log::error('wanlpay.php extHandle');
        \think\Log::error($oid);//924
        \think\Log::error($uid);//91
        bcscale(2);
        $order = Order::find($oid);
        $pay = \app\api\model\wanlshop\Pay::where('order_id', $oid)->find();
        \think\Log::error($order->state);
        \think\Log::error($pay->pay_type);
        \think\Log::error("extHandle,oid:$oid,uid:$uid,order:" . $order->state . ",pay_type:" . $pay->pay_type);
        if ($order->state != 1) {
            return true;
        }

        \think\Log::error("Order::scoreHandle ..");
        Order::scoreHandle($oid, $uid);
        \think\Log::error("Order::scoreHandle end..");

        \think\Log::error("print end ..");
        //dayin
        $this->print($oid);
        \think\Log::error("print end ..");
        \think\Log::error("score handle end ..");
        $this->shareAgentOrderHandle($oid, $uid, $pay['price']);
        \think\Log::error("shareAgentOrderHandle end ..");

        //同步第三方
        $thrid = new Thirdplatform();
//        $res = $thrid->pay($pay->order_no, 4);
        \think\Log::error('$pay->order_no->' . $pay->order_no);
        $res = $thrid->pay2($pay->order_no, 4);
        if ($res !== true) {
            return $res;
        }
        \think\Log::error("sync end ..");
        return true;
    }

    private function offlinePayment($sid, $amount)
    {
        \think\Log::error("offlinePayment($sid, $amount)");
        $amount = bcdiv($amount, 2.2, 2);
        if ($amount < 0.1) {
            \think\Log::error("返还金额不能小于0.1");
            return;
        }
        $config = \app\api\model\wanlshop\Shop::where('id', $sid)->find();
        if (empty($config->realname) || empty($config->account)) {
            \think\Log::error("店铺尚未配置提现数据sid:$sid,amount:$amount");
            return;
        }
        \think\Log::error('offlinePayment->amount->' . $amount);
        $this->offlineTransfer($sid . mt_rand(100000, 999999), $amount, $config->account, $config->realname);
        \think\Log::error("transfer end..");
    }

    public function offlineTransfer($order_no, $amount, $account, $name)
    {
        if ($amount < 0.1) {
            \think\Log::error("返还金额不能小于0.1");
            return true;
        }
        \think\Log::error("打款$name -- $account");
        \think\Log::error("order_no:$order_no, amount:$amount, account:$account, name:$name");
        $order = [
            'out_biz_no' => $order_no,
            'trans_amount' => $amount, //todo
//            'trans_amount' => 0.1,
            'product_code' => 'TRANS_ACCOUNT_NO_PWD',
            'biz_scene' => 'DIRECT_TRANSFER',
            'payee_info' => [
                'identity' => $account,
                'identity_type' => 'ALIPAY_LOGON_ID',
                'name' => $name,
            ],
        ];
        return Pay::alipay(self::getConfig('alipay'))->transfer($order);
    }

    public function shareAgentOrderHandle($oid, $uid, $price)
    {
        if ($price <= 0.01) {
            return true;
        }
        $config = get_addon_config('wanlshop');
        $config = $config['agent'];
        \think\Log::error($config);
        $shareOrder = ShareOrder::where(['order_id' => $oid, 'user_id' => $uid])->select();
        \think\Log::error("分销订单数量:" . count($shareOrder));
        if ($shareOrder) {
            foreach ($shareOrder as $item) {
                $model = Share::find($item['parent_share_id']);
                $model->waitting = bcadd($model->waitting, $item['parent_amount']);
                $model->save();
                \think\Log::error("增加上级分销{$item['parent_share_id']}级别{$model['level']}佣金{$item['parent_amount']}");
            }
        }

        $order = Order::find($oid);
        $agentOrder = AgentOrder::where(['order_id' => $oid, 'user_id' => $uid])->select();
        \think\Log::error("代理商订单数量:" . count($agentOrder));
        if ($agentOrder) {
            foreach ($agentOrder as $item) {
                if ($item['status'] == 1) {
                    \think\Log::error('item.status == 1 continue' . $item['id']);
                    continue;
                }
                $model = Agent::withTrashed()->find($item['parent_agent_id']);
                if ($config['switch'] == 'Y') {
                    $model->waitting = bcadd($model->waitting, $item['parent_amount']);
                    $model->save();
                    $this->offlineTransfer($item['order_sn'], $item['parent_amount'], $model['account'], $model['realname']);
                } else {
                    $user = User::find($model['user_id']);
                    $after = bcadd($user['money'], $item['parent_amount']);
                    UserFinanceLog::create([
                        'user_id' => $user['id'],
                        'type' => 'money',
                        'flag' => 'add',
                        'value' => $item['parent_amount'],
                        'before' => $user['money'],
                        'after' => $after,
                        'event' => 'sys',
                        'rel_id' => $item['id'],
                        'remark' => "代理佣金打款,agent_order.id:" . $item['id'],
                        'status' => 'succeed',
                        'createtime' => time(),
                        'updatetime' => time(),
                    ]);
                    \think\Log::error("insert finance log");
                    $user->money = $after;
                    $user->save();
                    \think\Log::error("update user money");

                    $agOrder = AgentOrder::find($item['id']);
                    $agOrder->pay_at = date('Y-m-d H:i:s');
                    $agOrder->status = 1;
                    $agOrder->save();
                    \think\Log::error("update AgentOrder status");

                    $order->finish_agent = 1;
                    $order->save();
                    \think\Log::error("update order finish_agent=1");

                    $model->amount = bcadd($model['amount'], $item['parent_amount']);
                    $model->save();
                    \think\Log::error("update agent amount");
                }
                \think\Log::error("增加上级代理商{$item['parent_agent_id']}级别{$model['level']}佣金{$item['parent_amount']}");
            }
        }
        \think\Log::error("offline_order $order->offline_order , real_store_id $order->real_store_id");
        \think\Log::error("switch {$config['switch']}");
        if ($order->offline_order == 1 && !empty($order->real_store_id)) {
            if ($config['switch'] == 'Y') {
                $order = Order::find($oid);
                if ($order->finish_offline == 1) {
                    return true;
                }
                \think\Log::error('线下实体店打款');

                $this->offlinePayment($order->real_store_id, $price);
                $this->offline_order_create($order,$price);
                $order->finish_offline = 1;
                $order->save();
            } else {
                $user = User::find($uid);
                $after = bcadd($user['money'], $price);
                UserFinanceLog::create([
                    'user_id' => $user['id'],
                    'type' => 'money',
                    'flag' => 'add',
                    'value' => $price,
                    'before' => $user['money'],
                    'after' => $after,
                    'event' => 'sys',
                    'rel_id' => 0,
                    'remark' => '',
                    'status' => 'succeed',
                    'createtime' => time(),
                    'updatetime' => time(),
                ]);
                \think\Log::error("insert finance log");
                $user->money = $after;
                $user->save();
                \think\Log::error("update user money");
            }
        }
    }


    public function offline_order_create($order, $price)
    {
        $OfflineOrder = new OfflineOrder();
        $data['user_id'] = $order['user_id'];
        $data['order_id'] = $order['id'];
        $data['shop_id'] = $order['shop_id'];
        $data['pay_amount'] = $price;
        $data['real_store_id'] = $order['real_store_id'];
        $data['amount'] = bcdiv($price, 2.2, 2);
        $data['created_at'] = $data['updated_at'] = date('Y-m-d H:i:s');
        \think\Log::error("order_state" . $order['state']);
//        if ($order['state'] > 2 && $order['state'] != 5 && $order['state'] != 7) {


        $data['pay_at'] = date('Y-m-d H:i:s');//
        $data['status'] = 1;//支付成功
//        }
        $data['order_sn'] = date('YmdHis') . mt_rand(100000, 999999);
        $OfflineOrder->save($data);
    }
}